﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DnEcuDiag.Ecus.Enums;
using DnEcuDiag.Ecus.Generic;
using DnEcuDiag.Ecus.Kwp;
using DnEcuDiag.Factories;
using NUnit.Framework;

namespace DnEcuDiag.Tests
{
    [TestFixture]
    public class ME21TTests
    {
        private KwpEcu _ecu;
        private KwpTestDevice _device;

        [TestFixtureSetUp]
        public void TestSetup()
        {
            _device = new KwpTestDevice();

            EcuDescriptor descriptor = EcuFactory.EcuList.Find(ecuDescriptor => ecuDescriptor.Name == "Bosch Motronic ME2.1 Turbo");

            _ecu = EcuFactory.CreateEcu(descriptor) as KwpEcu;
            Assert.IsNotNull(_ecu);
            _ecu.DiagnosticInterface = _device;
            _ecu.Connect();
        }

        [Test]
        public void TestIdentification()
        {
            Assert.AreEqual("Bosch Motronic ME2.1 Turbo", _ecu.Model);
            Assert.AreEqual("0123456789 ", _ecu.DrawingNumber);
            Assert.AreEqual("0123456789 ", _ecu.HardwareNumber);
            Assert.AreEqual("0x10", _ecu.HardwareVersionNumber);
            Assert.AreEqual("0123456789 ", _ecu.SoftwareNumber);
            Assert.AreEqual("0x85170", _ecu.SoftwareVersionNumber);
            Assert.AreEqual("01234 ", _ecu.OmologationNumber);
            Assert.AreEqual("55 AA 55 AA 55 ", _ecu.IsoCode);
            Assert.AreEqual("19 97 03 31 ", _ecu.ProductionDate);
            Assert.AreEqual("19 97 03 31 ", _ecu.ProgrammingDate);
            Assert.IsNotNull(_ecu.RpmSensor);
            Assert.AreEqual("Engine Speed", _ecu.RpmSensor.Name);
            Assert.IsNotNull(_ecu.SpeedSensor);
            Assert.AreEqual("Vehicle Speed (Low Res)", _ecu.SpeedSensor.Name);
            Assert.AreEqual(InitType.Standard, _ecu.InitType);
        }

        [Test]
        public void TestSensors()
        {
            TimeStampedMeasurement ts;

            Assert.AreEqual(100, _ecu.Sensors.Count);

            Console.WriteLine("ME2.1 Sensors");

            LocalIdentifier li = _ecu.Sensors[14] as LocalIdentifier;
            Console.WriteLine(li.Name);

            Assert.AreEqual(140, li.UpperLimit);
            Assert.AreEqual(-30, li.LowerLimit);
            Assert.AreEqual("Air Temperature", li.Name);

            _device.LocalidentifierData = new byte[] { 0x61, (Byte)li.Id, 0xFF };
            ts = _ecu.ReadSensor(_ecu.Sensors[14]);
            Assert.AreEqual(string.Empty, ts.Status);
            Assert.AreEqual(140, ts.Measurement);

            _device.LocalidentifierData = new byte[] { 0x61, (Byte)li.Id, 0x0 };
            ts = _ecu.ReadSensor(_ecu.Sensors[14]);
            Assert.AreEqual(string.Empty, ts.Status);
            Assert.AreEqual(-40, ts.Measurement);

            _device.LocalidentifierData = new byte[] { 0x61, (Byte)li.Id, 0x55 };
            ts = _ecu.ReadSensor(_ecu.Sensors[14]);
            Assert.AreEqual(string.Empty, ts.Status);
            Assert.AreEqual(7.2f, ts.Measurement);

            li = _ecu.Sensors[15] as LocalIdentifier;
            Console.WriteLine(li.Name);

            Assert.AreEqual(400, li.UpperLimit);
            Assert.AreEqual(0, li.LowerLimit);
            Assert.AreEqual("Air Mass Flow", li.Name);

            li = _ecu.Sensors[29] as LocalIdentifier;
            Console.WriteLine(li.Name);

            Assert.AreEqual("Lambda Sensor Pre-catalyser Row #1", li.Name);
            Assert.AreEqual(1000, li.UpperLimit);
            Assert.AreEqual(0, li.LowerLimit);

            _device.LocalidentifierData = new byte[] { 0x61, (Byte)li.Id, 0xff };
            ts = _ecu.ReadSensor(_ecu.Sensors[29]);
            Assert.AreEqual(string.Empty, ts.Status);
            Assert.AreEqual(4845, ts.Measurement);

            _device.LocalidentifierData = new byte[] { 0x61, (Byte)li.Id, 0x55 };
            ts = _ecu.ReadSensor(_ecu.Sensors[29]);
            Assert.AreEqual(string.Empty, ts.Status);
            Assert.AreEqual(1615, ts.Measurement);

            _device.LocalidentifierData = new byte[] { 0x61, (Byte)li.Id, 0x0 };
            ts = _ecu.ReadSensor(_ecu.Sensors[29]);
            Assert.AreEqual(string.Empty, ts.Status);
            Assert.AreEqual(0, ts.Measurement);
        }

        [Test]
        public void TestActuators()
        {
            Assert.AreEqual(16, _ecu.Actuators.Count);
        }

        [Test]
        public void TestPerformanceMeasurment()
        {
            Assert.AreNotEqual(null, _ecu.SpeedSensor);
            Assert.AreNotEqual(null, _ecu.RpmSensor);
        }

        [Test]
        public void TestFaults()
        {
            Assert.AreNotEqual(0, _ecu.ErrorMemoryStructureDefinition.ErrorDefinitions.Count, "_ecu.ErrorMemoryStructureDefinition.Count == 0");
            Assert.AreEqual(47, _ecu.ErrorMemoryStructureDefinition.ErrorDefinitions.Count, "_ecu.ErrorMemoryStructureDefinition.Count != 47");

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // Three P0100
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////			
            _device.FaultcodeList = new byte[] { 0x58, 03, 01, 00, 0xE2, 01, 00, 0xE2, 01, 00, 0xE2 };
            _device.Faultcodeinfo = new byte[13] { 0x61, 0x10, 0x01, 0x00, 0xE2, 0x1D, 0x0D, 0x00, 0x00, 0xA, 0x0A, 0x40, 0x00 };
            _ecu.ReadFaultCodes();


            Assert.AreEqual(3, _ecu.ActiveFaultCodes.Count, "_ecu.ActiveFaultCodes.Count == 3 for ME2.1");
            Console.WriteLine(_ecu.ActiveFaultCodes[0].FaultDescription);
            Assert.AreEqual("P0100", (_ecu.ActiveFaultCodes[0]).FaultComponent);
            Assert.AreEqual("Failed Component Code: Air Flow Meter\r\nFault Symptom: Below Minimum Limit\r\n" +
                "Warning Lamp Status: Warning Lamp Illuminated\r\nFault Test State: Test complete for this Error or not applicable." +
                "\r\nFault Code Storage State: Error Present at time of request\r\nEvent Count: 64 count\r\n" +
                "Filter Count: 0 count\r\n" +
                "Environmental Condition One: Engine Speed: 29 rpm\r\n" +
                "Environmental Condition Two: Standardised Engine Loading: 9.75 %\r\n" +
                "Environmental Condition Three: Engine Coolant Temperature: -59 °C\r\n" +
                "Environmental Condition Four: Air Temperature: -50.1 °C\r\n" +
                "Environmental Condition Five: Throttle Valve Angle: 3.13 °\r\n" +
                "Environmental Condition Six: Battery Voltage: 0.94 volts\r\n",
                _ecu.ActiveFaultCodes[0].FaultDescription);


            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // U1601
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////			
            _device.FaultcodeList = new byte[] { 0x58, 0x01, 0xD6, 0x01, 0xE8 };
            _device.Faultcodeinfo = new byte[13] { 0x61, 0x10, 0xD6, 0x01, 0xE8, 0x1D, 0x0D, 0x00, 0x00, 0xA, 0x0A, 0x40, 0x00 };
            _ecu.ReadFaultCodes();

            Assert.AreEqual(1, _ecu.ActiveFaultCodes.Count, "_ecu.ActiveFaultCodes.Count == 1 for M.1.5.5");
            Console.WriteLine(_ecu.ActiveFaultCodes[0].FaultDescription);
            Assert.AreEqual("U1601", (_ecu.ActiveFaultCodes[0]).FaultComponent);
            Assert.AreEqual("Failed Component Code: CAN error\r\nFault Symptom: Signal Not Plausible\r\n" +
                "Warning Lamp Status: Warning Lamp Illuminated\r\nFault Test State: Test complete for this Error or not applicable." +
                "\r\nFault Code Storage State: Error Present at time of request\r\nEvent Count: 64 count\r\n" +
                "Filter Count: 0 count\r\n" +
                "Environmental Condition One: Engine Speed: 29 rpm\r\n" +
                "Environmental Condition Two: Standardised Engine Loading: 9.75 %\r\n" +
                "Environmental Condition Three: Engine Coolant Temperature: -59 °C\r\n" +
                "Environmental Condition Four: Air Temperature: -50.1 °C\r\n" +
                "Environmental Condition Five: Throttle Valve Angle: 3.13 °\r\n" +
                "Environmental Condition Six: Battery Voltage: 0.94 volts\r\n",
                _ecu.ActiveFaultCodes[0].FaultDescription);

            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            // U1600
            //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////			
            _device.FaultcodeList = new byte[] { 0x58, 0x01, 0xD6, 0x00, 0xE8 };
            _device.Faultcodeinfo = new byte[13] { 0x61, 0x10, 0xD6, 0x01, 0xE8, 0x1D, 0x0D, 0x00, 0xFF, 0xA, 0x0A, 0x40, 0x00 };
            _ecu.ReadFaultCodes();

            Assert.AreEqual(1, _ecu.ActiveFaultCodes.Count, "_ecu.ActiveFaultCodes.Count == 1 for M.1.5.5");
            Console.WriteLine(_ecu.ActiveFaultCodes[0].FaultDescription);
            Assert.AreEqual("U1600", (_ecu.ActiveFaultCodes[0]).FaultComponent);
            Assert.AreEqual("Failed Component Code: Immobiliser\r\nFault Symptom: Signal Not Plausible\r\n" +
                "Warning Lamp Status: Warning Lamp Illuminated\r\nFault Test State: Test complete for this Error or not applicable." +
                "\r\nFault Code Storage State: Error Present at time of request\r\nEvent Count: 64 count\r\n" +
                "Filter Count: 0 count\r\n" +
                "Environmental Condition One: Engine Speed: 29 rpm\r\n" +
                "Environmental Condition Two: Standardised Engine Loading: 9.75 %\r\n" +
                "Environmental Condition Three: Engine Coolant Temperature: -59 °C\r\n" +
                "Environmental Condition Four: Immobiliser: Not ok\r\n" +
                "Environmental Condition Four: Immobiliser: No code received or link interrupted\r\n" +
                "Environmental Condition Four: Immobiliser: Erroneous key code\r\n" +
                "Environmental Condition Four: Immobiliser: Virgin Ecu\r\n" +
                "Environmental Condition Four: Immobiliser: Engine Start Disabled\r\n" +
                "Environmental Condition Four: Immobiliser: Universal Code Received\r\n" +
                "Environmental Condition Five: Throttle Valve Angle: 3.13 °\r\n" +
                "Environmental Condition Six: Battery Voltage: 0.94 volts\r\n",
                _ecu.ActiveFaultCodes[0].FaultDescription);
        }
    }
}
